package io.adrainty.bolee.security.configuration;

import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
import cn.hutool.core.text.StrPool;
import io.adrainty.bolee.framework.commons.basic.ResultDTO;
import io.adrainty.bolee.framework.commons.utils.EnumUtil;
import io.adrainty.bolee.framework.commons.utils.ResultDTOUtil;
import io.adrainty.bolee.security.feign.IClientFeign;
import io.adrainty.bolee.security.models.constants.OAuth2Constants;
import io.adrainty.bolee.security.models.entity.ClientEntity;
import io.adrainty.bolee.security.models.valobj.GrantTypeEnum;
import io.adrainty.bolee.security.satoken.register.GrantTypeHandlerRegister;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>SaTokenOauthConfig</p>
 *
 * @author AdRainty
 * @version V1.0.0
 * @description SaTokenOauthConfig
 * @since 2025/8/6 14:36:17
 */

@Slf4j
@Configuration
public class SaTokenOauthConfig implements SaOAuth2DataLoader {

    @Resource
    private IClientFeign clientFeign;

    /**
     * 配置 Sa-Token OAuth2 Server端
     *
     * @param handlerRegister GrantTypeHandlerRegister
     * @param oauth2Server    SaOAuth2ServerConfig
     */
    @Autowired
    public void configOAuth2Server(SaOAuth2ServerConfig oauth2Server, GrantTypeHandlerRegister handlerRegister) {
        // 添加 client
        List<ClientEntity> clientEntities;
        try {
            ResultDTO<List<ClientEntity>> resultDTO = clientFeign.getClientList();
            clientEntities = ResultDTOUtil.assertResultDataNotNull(resultDTO);
        } catch (Exception e) {
            log.error("获取客户端列表失败: ", e);
            clientEntities = new ArrayList<>();
        }

        for (ClientEntity clientEntity : clientEntities) {
            SaClientModel model = convertClientModel(clientEntity);
            oauth2Server.addClient(model);
        }

        SaOAuth2Strategy.instance.grantTypeAuth = req -> {
            String grantType = req.getParam(OAuth2Constants.GRANT_TYPE_KEY);
            String clientId = req.getParam(OAuth2Constants.CLIENT_ID_KEY);

            GrantTypeEnum grantTypeEnum = EnumUtil.getEnumConstants(grantType, GrantTypeEnum.class);
            if (GrantTypeEnum.REFRESH_TOKEN.equals(grantTypeEnum)) {
                return handlerRegister.getHandlerInterface(grantTypeEnum.getCode()).getAccessToken(req, clientId, null);
            }

            String loginType = req.getParam(OAuth2Constants.LOGIN_TYPE_KEY);
            loginType = loginType.split(StrPool.DASHED)[1];
            return handlerRegister.getHandlerInterface(loginType).getAccessToken(req, clientId, null);
        };
    }

    @Override
    public SaClientModel getClientModel(String clientId) {
        ResultDTO<ClientEntity> resultDTO = clientFeign.getClientEntity(clientId);
        ClientEntity clientEntity = ResultDTOUtil.assertResultDataNotNull(resultDTO);
        return convertClientModel(clientEntity);
    }

    private static SaClientModel convertClientModel(ClientEntity clientEntity) {
        SaClientModel model = new SaClientModel();
        model.setClientId(clientEntity.getClientId());
        model.setClientSecret(clientEntity.getClientSecret());
        model.addAllowRedirectUris(StringUtils.defaultIfBlank(clientEntity.getWebServerRedirectUri(), "*"));
        model.addContractScopes(clientEntity.getScope().split(StrPool.COMMA));
        model.addAllowGrantTypes(clientEntity.getAuthorizedGrantTypes().split(StrPool.COMMA));
        return model;
    }
}
